For most platforms, you can write subsystems which abstract away from the specific APIs used to call out and get information back from the platform you're running on. IO APIs are usually the easiest to abstract - all file systems work on some pretty basic assumptions about opening, closing and reading from files, even when you factor in asynchronous calling. Then you have your core systems like reading controller input, querying the time, accessing memory and thread primitives, most of which work the same way.
Even graphics can be abstracted to a large extent, and indeed in most good engines they are. But you have to package up the 'renderable' things into black boxes where you aren't allowed to know what's going on inside them. You know that you have a 'thing' which you render in a particular position in the world. You don't know how it's rendered, just that it is. And the graphics abstraction layer takes care of all of the details of getting it on-screen. The platform specific build pipelines package up the graphical data in such a way that it can be referenced from the engine without really knowing how it's represented internally.
All that said though, when it comes down to actually shipping a game, there are certain parts that you just can't abstract away. It would be ridiculous to think you could ship the same code on iPhone as you would on 360 or PS3, as the input mechanisms, fundamental way of operating, and platform capabilities are just too different. You could make an iPhone sized title on 360, but it would have to limit its input mechanisms to only those that the 360 can support. So, a virtual cursor on screen simulating a finger, and possibly using the joystick where the 3D accelerometer input is used.
More sensibly, parts of the game can be written in a re-usable way, and individual code modules can be ported between platforms, even though the majority of the title is different. For example if you have an AI state machine, that doesn't really care whether it's running on 360, PC, or iPhone. Your game will use many such components, and as long as they've been designed well so that they take well defined inputs and outputs, then the rest of a game can be wrapped around them, regardless of platform, and avoid having to rewrite those components.
That re-usability is the key to a cross platform development, not looking for a one-size-fits-all engine which works on all platforms. Even if such a thing did exist, it would be so crippled by having to work on the lowest common denominator, it wouldn't be of much use to make games with.