/*! @file eltorito.c Copyright 2007 VMware Inc. Author: David Elliott */ #include "boot.h" //========================================================================== // El Torito calls static biosBuf_t bb; // True if the address can be represented in real mode // i.e. it is only 20 bits // NOTE: Yes.. I do know about the UMA hack.. but that's silly for our purposes #define IS_ADDR_REAL(addr32) (((addr32) & ~0xFFFFF) == 0) // Returns the El Torito return code (AH) int elToritoGetStatus(int biosdev, struct el_torito_spec_packet *p_cd_spec) { struct el_torito_spec_packet cd_spec; struct el_torito_spec_packet *_p_cd_spec = ((p_cd_spec != NULL) && IS_ADDR_REAL((uint32_t)p_cd_spec))?p_cd_spec:&cd_spec; bzero(_p_cd_spec, sizeof(struct el_torito_spec_packet)); _p_cd_spec->packet_size = sizeof(struct el_torito_spec_packet); bb.intno = 0x13; bb.eax.r.h = 0x4b; bb.eax.r.l = 1; // Status only. Do not terminate bb.edx.rx = biosdev; bb.esi.rr = OFFSET((uint32_t)_p_cd_spec); bb.ds = SEGMENT((uint32_t)_p_cd_spec); bios(&bb); if(p_cd_spec != NULL && _p_cd_spec != p_cd_spec) bcopy(_p_cd_spec, p_cd_spec, sizeof(struct el_torito_spec_packet)); return bb.eax.r.h; } // Terminating then initiating the emulation does not seem to work // and is not needed anyway as the disc can be replaced without it. #if 0 // Returns the El Torito return code (AH) int elToritoInitiateDiskEmulation(int biosdev, struct el_torito_spec_packet *p_cd_spec) { struct el_torito_spec_packet cd_spec; struct el_torito_spec_packet *_p_cd_spec = ((p_cd_spec != NULL) && IS_ADDR_REAL((uint32_t)p_cd_spec))?p_cd_spec:&cd_spec; if(p_cd_spec == NULL) stop("Cannot initiate El Torito emulation without knowing the specification packet"); if(_p_cd_spec != p_cd_spec) bcopy(p_cd_spec, _p_cd_spec, sizeof(struct el_torito_spec_packet)); bb.intno = 0x13; bb.eax.r.h = 0x4a; bb.eax.r.l = 0; // Initiate bb.edx.rx = biosdev; bb.esi.rr = OFFSET((uint32_t)_p_cd_spec); bb.ds = SEGMENT((uint32_t)_p_cd_spec); bios(&bb); if(p_cd_spec != NULL && _p_cd_spec != p_cd_spec) bcopy(_p_cd_spec, p_cd_spec, sizeof(struct el_torito_spec_packet)); return bb.eax.r.h; } #endif // Returns the El Torito return code (AH) int elToritoTerminateDiskEmulation(int biosdev, struct el_torito_spec_packet *p_cd_spec) { struct el_torito_spec_packet cd_spec; struct el_torito_spec_packet *_p_cd_spec = ((p_cd_spec != NULL) && IS_ADDR_REAL((uint32_t)p_cd_spec))?p_cd_spec:&cd_spec; bzero(_p_cd_spec, sizeof(struct el_torito_spec_packet)); _p_cd_spec->packet_size = sizeof(struct el_torito_spec_packet); bb.intno = 0x13; bb.eax.r.h = 0x4b; bb.eax.r.l = 0; // Terminate bb.edx.rx = biosdev; bb.esi.rr = OFFSET((uint32_t)_p_cd_spec); bb.ds = SEGMENT((uint32_t)_p_cd_spec); bios(&bb); if(p_cd_spec != NULL && _p_cd_spec != p_cd_spec) bcopy(_p_cd_spec, p_cd_spec, sizeof(struct el_torito_spec_packet)); return bb.eax.r.h; }